package com.evil.account.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.evil.account.pojo.entity.Role;
import com.evil.common.account.dto.role.RoleBaseRespDTO;
import com.evil.common.account.dto.role.RolePageReqDTO;
import com.evil.common.account.dto.role.RolePageRespDTO;
import com.evil.common.account.util.AccountRedisKeyUtil;
import com.evil.common.core.constant.RedisConstant;
import com.evil.common.core.entity.QueryModel;
import com.evil.common.core.enums.RCodeEnum;
import com.evil.common.core.enums.SwitchEnum;
import com.evil.common.core.exception.BusinessException;
import com.evil.common.core.util.CacheMapperUtil;
import com.evil.common.core.util.StreamUtil;
import com.evil.common.db.mapper.BatchMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.ibatis.annotations.Param;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 角色表
 *
 * @author liyang
 * @date 2022-08-08 00:00
 */
public interface RoleMapper extends BaseMapper<Role>, BatchMapper<Role, Long> {

    int updateBatch(List<Role> list);

    int batchInsert(@Param("list") List<Role> list);

    default Role findById(Long id) {
        return this.selectById(id);
    }

    List<Role> findByIds(@Param("ids") Collection<Long> ids, @Param("filterDeleted") boolean filterDeleted);

    default Optional<Role> isExistById(Long id) {
        return Optional.ofNullable(this.selectById(id));
    }

    default Optional<Role> isExistById_Cache(Long id) {
        return CacheMapperUtil.cacheById(
                id,
                Role.class,
                this::findById,
                AccountRedisKeyUtil::requestUuidRoleKey,
                RedisConstant.REQUEST_UUID_EXPIRE_IN_SECOND
        );
    }

    default Role findById_Cache(Long id) {
        return this.isExistById(id).orElseThrow(() -> new BusinessException(RCodeEnum.USER_NOT_EXIST));
    }

    RoleBaseRespDTO findBaseById(@Param("id") Long id);

    default Role findNormalById(Long id) {
        return this.isExistById(id)
                .filter(d -> !SwitchEnum.isOpen(d.getIsDeleted()))
                .orElseThrow(() -> new BusinessException(RCodeEnum.USER_NOT_EXIST));
    }

    Optional<Role> isExistByEnterpriseRoleCode(@Param("enterpriseId") Long enterpriseId,
                                               @Param("roleCode") String roleCode);

    List<RoleBaseRespDTO> findBaseByIds(@Param("ids") Collection<Long> ids, @Param("filterDeleted") boolean filterDeleted);

    List<RoleBaseRespDTO> roleBases(RolePageReqDTO rolePageReqDTO);

    List<Role> findByEnterpriseId(@Param("enterpriseId") Long enterpriseId);

    default List<RoleBaseRespDTO> findBaseByIds_Cache(Collection<Long> ids, boolean filterDeleted) {
        return CacheMapperUtil.cacheByIds(
                ids,
                filterDeleted,
                RoleBaseRespDTO.class,
                this::findBaseByIds,
                RoleBaseRespDTO::getRoleId,
                u -> SwitchEnum.NO.getId(),
                null,
                AccountRedisKeyUtil::requestUuidRoleBaseKeyMap,
                RedisConstant.REQUEST_UUID_EXPIRE_IN_SECOND
        );
    }

    default Map<Long, Role> findMapByIds(Collection<Long> ids, boolean filterDeleted) {
        return StreamUtil.toMapK(this.findByIds(ids, filterDeleted), Role::getRoleId);
    }

    default Map<Long, RoleBaseRespDTO> findBaseMapByIds(Collection<Long> ids, boolean filterDeleted) {
        return StreamUtil.toMapK(this.findBaseByIds(ids, filterDeleted), RoleBaseRespDTO::getRoleId);
    }

    List<RolePageRespDTO> roles(RolePageReqDTO rolePageReqDTO);

    default PageInfo<RolePageRespDTO> rolePage(QueryModel<RolePageReqDTO> queryModel) {
        return PageHelper.startPage(queryModel.getPageNum(), queryModel.getPageSize(), queryModel.initOrder())
                .doSelectPageInfo(() -> this.roles(queryModel.getParam()));
    }
}